package block;

import beans.BlockBean;
import beans.NonceAndHash;
import beans.ProofOfWork;
import pow.pow;
import utils.Hash;

import java.util.Date;

/**
 * @author:zhengyilong
 * @email:1797344574@qq.com
 * @phone:13479394730
 * @desc:
 * @DateTime:2022/5/14 9:18
 **/
public class Block {

    private static BlockBean blockBean = new BlockBean();

    /**
     * 创建新区块
     * @param data 交易数据
     * @param prevBlockHash 上一个区块的哈希
     * @return 返回一个BlockBean对象
     */
    public static BlockBean NewBlock(String data,byte[] prevBlockHash){
        blockBean.setTimestamp(new Date().getTime());
        blockBean.setData(data.getBytes());
        blockBean.setPrevBlockHash(prevBlockHash);
        //SetHash();
        //寻找随机数并重新进行哈希计算
        ProofOfWork proofOfWork = pow.NewProofOfwork(blockBean);
        NonceAndHash nonceAndHash = pow.Run(proofOfWork);
        blockBean.setHash(nonceAndHash.getHash());
        blockBean.setNonce(nonceAndHash.getNonce());
        return blockBean;
    }

    /**
     * 该方法用于创建一个创世区块
     * @param data 交易数据
     * @return 返回一个区块对象
     */
    public static BlockBean NewGenesisBlock(String data) {
        return NewBlock(data,null);
    }

    /**
     * 将区块进行sha256加密得到哈希值，并设置进BlockBean对象中
     */
    private static void SetHash(){
        //将long类型的时间戳转成bute[]类型
        long timestamp = blockBean.getTimestamp();
        String timestampToString = Long.toString(timestamp);
        byte[] timestampToStringBytes = timestampToString.getBytes();

        //声明一个长度为三个字段总长度的数组
        //两次判空，防止创建的是创世区块，没有上一个区块哈希值报空指针异常
        byte[] bytes;
        if (blockBean.getPrevBlockHash() != null){
            bytes = new byte[timestampToStringBytes.length+blockBean.getData().length+blockBean.getPrevBlockHash().length];
        }else {
            bytes = new byte[timestampToStringBytes.length+blockBean.getData().length];
        }

        /**
         * 拼接数组
         * 第一个参数：原数组
         * 第二个参数：从原数组的起始位置开始
         * 第三个参数：目标数组
         * 第四个参数：目标数组的开始起始位置
         * 第五个参数：要copy的数组的长度
         */
        System.arraycopy(timestampToStringBytes,0,bytes,0,timestampToStringBytes.length);
        System.arraycopy(blockBean.getData(),0,bytes,timestampToStringBytes.length,blockBean.getData().length);
        //两次判空，防止创建的是创世区块，没有上一个区块哈希值报空指针异常
        if (blockBean.getPrevBlockHash() != null){
            System.arraycopy(blockBean.getPrevBlockHash(),0,bytes,timestampToStringBytes.length+blockBean.getData().length,blockBean.getPrevBlockHash().length);
        }

        //调用自动义加密方法对拼接后的区块信息进行加密
        byte[] sha256 = Hash.SHA256(bytes);
        //将加密后的哈希值设置进Blockbean对象中
        blockBean.setHash(sha256);
    }

}

